package com.kfm.kfmchat.controller;


import cn.hutool.http.Header;
import cn.hutool.http.HttpRequest;
import cn.hutool.json.JSONObject;
import com.kfm.kfmchat.listener.ChatEventSourceListener;
import com.unfbx.chatgpt.OpenAiStreamClient;
import com.unfbx.chatgpt.entity.chat.ChatCompletion;
import com.unfbx.chatgpt.entity.chat.Message;
import com.unfbx.chatgpt.interceptor.OpenAILogger;
import com.unfbx.chatgpt.interceptor.OpenAiResponseInterceptor;
import okhttp3.OkHttpClient;
import okhttp3.logging.HttpLoggingInterceptor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.util.Arrays;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

@RestController
public class ChatController {

    @RequestMapping("/chat/ask")
    public String chat(@RequestParam("question") String question) {
        return send(question);
    }


    private String send(String message) {
        String api_host = "https://ycdl.ysywy.shop/v1/chat/completions";
        String json = "{\n" +
                "     \"model\": \"gpt-3.5-turbo\",\n" +
                "     \"messages\": [{\"role\": \"user\", \"content\": \"" + message + "\"}],\n" +
                "     \"temperature\": 0.7\n" +
                "   }";
        String api_key = "sk-***";
        String result = HttpRequest.post(api_host)
                .header(Header.AUTHORIZATION, "Bearer " + api_key)
                .header(Header.CONTENT_TYPE, "application/json")
                .body(json)
                .execute().body();
        return new JSONObject(result).getJSONArray("choices").getJSONObject(0).getJSONObject("message").getStr("content");
    }

    private static final SseEmitter ss = new SseEmitter();

    @GetMapping("/stream")
    public SseEmitter stream() throws IOException {

        new Thread(() -> {
            try {
                for (int i = 0; i < 10; i++) {
                    Thread.sleep(1000);
                    ss.send(SseEmitter.event().id("1").name("message").data("hello"));
                }
            } catch (IOException e) {
                throw new RuntimeException(e);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }).start();
        return ss;
    }

    @RequestMapping("/chat/s")
    public SseEmitter streamChat(String message) throws IOException {
        return sendStream();
    }

    public SseEmitter sendStream() {
        OpenAiStreamClient client = OpenAiStreamClient.builder()
                .apiKey(Arrays.asList("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"))
                .okHttpClient(getOkHttpClient())
                .apiHost("https://ycdl.ysywy.shop/")
                .build();
        // 构建一个向 控制台 输出内容的对象
        // ConsoleEventSourceListener eventSourceListener = new ConsoleEventSourceListener();
        // 聊天模型：gpt-3.5
        Message message = Message.builder().role(Message.Role.USER).content("Java连接数据库").build();
        // 发送请求时候的请求体对象 model属性 messages 属性
        ChatCompletion chatCompletion = ChatCompletion.builder().temperature(0.7).messages(Arrays.asList(message)).build();
        SseEmitter sseEmitter = new SseEmitter(0L);
        ChatEventSourceListener chatEventSourceListener = new ChatEventSourceListener();
        chatEventSourceListener.setSseEmitter(sseEmitter);
        client.streamChatCompletion(chatCompletion, chatEventSourceListener);
        return sseEmitter;
    }

    public OkHttpClient getOkHttpClient() {
        Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("127.0.0.1", 7890));
        HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor(new OpenAILogger());
        //！！！！千万别再生产或者测试环境打开BODY级别日志！！！！
        //！！！生产或者测试环境建议设置为这三种级别：NONE,BASIC,HEADERS,！！！
        httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.HEADERS);
        return new OkHttpClient
                .Builder()
                .addInterceptor(httpLoggingInterceptor)//自定义日志输出
                .addInterceptor(new OpenAiResponseInterceptor())//自定义返回值拦截
                .connectTimeout(10, TimeUnit.SECONDS)//自定义超时时间
                .writeTimeout(30, TimeUnit.SECONDS)//自定义超时时间
                .readTimeout(30, TimeUnit.SECONDS)//自定义超时时间
                .build();
    }
}
